﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Adapter.SAP;
using System.Collections.Specialized;
using SAPInvoker.Reflector;
using SAPInvoker.Controls;
namespace SAPInvoker
{
    public partial class Form1 : Form
    {
        private int createThreadId;
        private System.Threading.WaitCallback wcExcption;
        private System.Threading.WaitCallback wcExecResult;
        public Form1()
        {
            InitializeComponent();
            this.createThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
            this.wcExcption = new System.Threading.WaitCallback(this.WriteExcption);
            this.wcExecResult = new System.Threading.WaitCallback(this.WriteExecResult);

            this.dataGridView1.AutoGenerateColumns = true;
        }

        private void btnInvoke_Click(object sender, EventArgs e)
        {
            this.lblException.Text = "";
            this.lblAlert.ForeColor = Color.Red;
            this.BeginInvoke(new Func<object>(DownLoad));
        }


        private object DownLoad()
        {
            try
            {

                SAPConnection con;
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                string connName = this.listBox1.SelectedItem.ToString();
                if (string.IsNullOrEmpty(connName))
                {
                    con = null;
                    MessageBox.Show("Select Enviroment Please");
                    return null;
                }
                else
                {
                    con = GetSAPConnection(connName);
                }


                con.Open();

                SAPCommand cmd = new SAPCommand(con);

                NameValueCollection nvCols = new NameValueCollection();
                if (!this.textBox1.Text.Trim().StartsWith("EXEC", StringComparison.InvariantCultureIgnoreCase))
                {
                    cmd.CommandText = AnalysisSql(this.textBox1.Text, out nvCols);//"SELECT * FROM MARD WHERE WERKS = 'AHIA'";

                }
                else
                {
                    cmd.CommandText = this.textBox1.Text;//"SELECT * FROM MARD WHERE WERKS = 'AHIA'";

                }
                sw.Start();
                SAPDataReader dr = cmd.ExecuteReader();
                // object obj= cmd.ExecuteScalar();
                DataTable dt = dr.GetSchemaTable();
                DataTable dtResult = new DataTable();
                foreach (DataRow dataRow in dt.Rows)
                {
                    dtResult.Columns.Add(dataRow["ColumnName"].ToString(), typeof(string));
                }

                while (dr.Read())
                {
                    DataRow newDataRow = dtResult.NewRow();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        string value = dr.GetValue(i).ToString();
                        newDataRow[i] = value;
                    }
                    dtResult.Rows.Add(newDataRow);
                    // string line = dr.GetValue(0).ToString();
                    //Console.WriteLine(line);
                }
                con.Close();

                AddConstColumns(ref dtResult, nvCols);
                this.dataGridView1.DataSource = dtResult;

                for (int k = 0; k < dataGridView1.ColumnCount; k++)
                {
                    dataGridView1.AutoResizeColumn(k);
                }
                dataGridView1.AllowUserToResizeColumns = true;
                this.lblAlert.Visible = true;
                sw.Stop();
                Program.WriteExecResult( "Rows Count is:" + dtResult.Rows.Count + ",Cost time is " + sw.ElapsedMilliseconds + "ms");
               // this.lblAlert.Text = "Rows Count is:" + dtResult.Rows.Count + ",Cost time is " + sw.ElapsedMilliseconds + "ms";
            }
            catch (Exception ex)
            {
                Program.WriteExcetion(ex.Message);
               // this.lblException.Text = ex.Message;
            }
            return null;
        }

        private void btnDiscover_Click(object sender, EventArgs e)
        {
            string rfcName = this.txtRFCName.Text.Trim();
            if (string.IsNullOrEmpty(rfcName))
            {
                MessageBox.Show("Must input Rfc/Bapi Name");
                return;
            }
            string connName = this.listRFCSAPConn.SelectedItem.ToString();
            if (string.IsNullOrEmpty(connName))
            {
                MessageBox.Show("Must Select SAP Conn Name");
                return;
            }
            SAPConnection conn = GetSAPConnection(connName);
            RFCParametersDiscover discover = new RFCParametersDiscover();
            RFCParametersInfo paramsInfo = discover.GetRFCParametersInfo(rfcName, conn);

            this.flowLayoutExportParams.Controls.Clear();
            this.panelTableParams.Controls.Clear();
            this.flowLayoutInputParams.Controls.Clear();
            foreach (RFCParameter p in paramsInfo.InParams.OrderBy(item => item.Position))
            {
                NormalRFCParameterInput normalParam = new NormalRFCParameterInput();
                normalParam.Parameter = p;
                normalParam.Direction = Direction.INPUT;
                this.flowLayoutInputParams.Controls.Add(normalParam);
            }
            foreach (RFCParameter p in paramsInfo.OutParams.OrderBy(item => item.Position))
            {
                NormalRFCParameterInput normalParam = new NormalRFCParameterInput();
                normalParam.Parameter = p;
                normalParam.Direction = Direction.OUTPUT;
                this.flowLayoutExportParams.Controls.Add(normalParam);
            }
            TableInput tabInput = new TableInput();
            tabInput.Name = "tabInputControl";
            tabInput.BindData(paramsInfo.TableParams);
            this.panelTableParams.Controls.Add(tabInput);
            this.btnInvokeRFC.Visible = true;
        }


        #region  Deal with Sql
        private string AnalysisSql(string sqlText, out System.Collections.Specialized.NameValueCollection nvConstColumns)
        {
            nvConstColumns = new System.Collections.Specialized.NameValueCollection();
            int startIndex = sqlText.IndexOf("SELECT", StringComparison.OrdinalIgnoreCase) + 6;
            int endIndex = sqlText.IndexOf("FROM", StringComparison.OrdinalIgnoreCase);
            string strColumns = sqlText.Substring(startIndex, endIndex - startIndex);
            string[] arrColumns = strColumns.Split(",".ToCharArray());
            string queryCols = "";
            foreach (string strCol in arrColumns)
            {
                if (strCol.Trim().StartsWith("'") && strCol.Trim().EndsWith("'"))
                {
                    nvConstColumns.Add(strCol.Trim().Trim("'".ToCharArray()), strCol.Trim().Trim("'".ToCharArray()));
                }
                else
                {
                    queryCols = queryCols + strCol + ",";
                }
            }
            queryCols = queryCols.TrimEnd(",".ToCharArray());
            int fromIndex = sqlText.IndexOf("FROM", StringComparison.OrdinalIgnoreCase);
            string conditionText = "";
            if (fromIndex > 0)
            {
                conditionText = sqlText.Substring(fromIndex);
            }

            string retSql = "SELECT " + queryCols + " " + conditionText;
            return retSql;

        }

        private void AddConstColumns(ref DataTable dtResult, NameValueCollection cols)
        {
            if (cols.Count > 0)
            {
                for (int i = 0; i < cols.Count; i++)
                {
                    dtResult.Columns.Add(cols.Keys[i], typeof(string));
                }
                foreach (DataRow dr in dtResult.Rows)
                {
                    for (int i = 0; i < cols.Count; i++)
                    {
                        dr[cols.Keys[i]] = cols[i];
                    }
                }
            }


        }
        #endregion

        #region
        private SAPConnection GetSAPConnection(string key)
        {
            string value = System.Configuration.ConfigurationManager.AppSettings["SAPCONN_" + key];
            return new SAPConnection(value);
        }
        #endregion

        private void btnInvokeRFC_Click(object sender, EventArgs e)
        {
            try
            {
                TableInput tableCrtl = this.panelTableParams.Controls["tabInputControl"] as TableInput;
                TableParamsInfo pinfo = null;
                if (tableCrtl != null)
                {
                    pinfo = tableCrtl.ParamsInfo;
                }
                string inputParamsSql = "";
                foreach (Control crtl in this.flowLayoutInputParams.Controls)
                {
                    NormalRFCParameterInput pCrtlInput = crtl as NormalRFCParameterInput;
                    if (pCrtlInput != null)
                    {
                        string tmpSql = pCrtlInput.ToSql();
                        if (!string.IsNullOrEmpty(tmpSql))
                        {
                            inputParamsSql = inputParamsSql+tmpSql + ",";
                        }
                    }
                }
                inputParamsSql = inputParamsSql.TrimEnd(",".ToCharArray());
                string outputParamsSql = "";
                foreach (Control crtl in this.flowLayoutExportParams.Controls)
                {
                    NormalRFCParameterInput pCrtlInput = crtl as NormalRFCParameterInput;
                    string tmpSql = pCrtlInput.ToSql();
                    if (!string.IsNullOrEmpty(tmpSql))
                    {
                        outputParamsSql = tmpSql + ",";
                    }
                }
                outputParamsSql = outputParamsSql.TrimEnd(",".ToCharArray());

                string paramsSql = "";
                if (!string.IsNullOrEmpty(inputParamsSql))
                {
                    paramsSql = paramsSql + inputParamsSql + ",";
                }
                if (pinfo != null)
                {
                    if (!string.IsNullOrEmpty(pinfo.SqlString))
                    {
                        paramsSql = paramsSql + pinfo.SqlString;
                    }
                }
                paramsSql = paramsSql.TrimEnd(",".ToCharArray());
                string rfcName = this.txtRFCName.Text.Trim();
                if (string.IsNullOrEmpty(rfcName))
                {
                    MessageBox.Show("Must input Rfc/Bapi Name");
                    return;
                }
                string connName = this.listRFCSAPConn.SelectedItem.ToString();
                if (string.IsNullOrEmpty(connName))
                {
                    MessageBox.Show("Must Select SAP Conn Name");
                    return;
                }
                SAPConnection conn = GetSAPConnection(connName);
                string execSql = string.Format("Exec {0} {1}", rfcName, paramsSql);
                SAPCommand cmd = new SAPCommand(conn);
                cmd.CommandText = execSql;
                foreach (SAPParameter p in pinfo.SAPParameters)
                {
                    cmd.Parameters.Add(p);
                }
                conn.Open();

                SAPDataReader dr = cmd.ExecuteReader();

                DataSet ds = new DataSet();
                foreach (SAPParameter p in cmd.Parameters)
                {
                    DataTable dt = p.Value as DataTable;
                    if (dt != null)
                    {
                        ds.Tables.Add(dt);
                    }
                }
                do
                {

                }
                while (dr.NextResult());

                this.panelTableParams.Controls.Clear();
                TableInput tabInput = new TableInput();
                tabInput.Name = "tabInputControl";
                tabInput.BindData(ds);
                this.panelTableParams.Controls.Add(tabInput);
                conn.Close();
            }
            catch (Exception ex)
            {
                Program.WriteExcetion(ex.Message);
            }
        }

        internal void WriteExcption(object msg)
        {
            if (this.CheckAccess())
            {
                this.lblException.Text = (string)msg;
               
            }
            else
            {
                this.BeginInvoke(this.wcExcption, msg);
            }
        }

        internal void WriteExecResult(object msg)
        {
            if (this.CheckAccess())
            {
              this.lblAlert.Text = (string)msg;
            }
            else
            {
                this.BeginInvoke(this.wcExecResult, msg);
            }
        }


        private bool CheckAccess()
        {
            return this.createThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId;
        }
    }
 
}
